/*
 * DART.cpp
 *
 *  Created on: May 23, 2011
 *      Author: ulas
 */

#include "DART.h"
DART::DART(U8 nodeId) : CLProtocol(nodeId)
{
	vCL =new vCLDART();
	DBG("DART Initiating, NODE_ID: %d\n", NODE_ID);
}

STATUS DART::gUpdate(const U8* msg, const U16 messageLength)
{
	U32 i, j;
	DART_MESSAGE_PARAMETER_TYPE par;
	U8 requiredSlots;


	par.numberOfFree = 0;
	par.numberOfNew = 0;
	if(messageLength > 0)
	{
		par.numberOfNew  = msg[0];
		par.numberOfFree = msg[1];
	}
	else {
		NOTIFY("gUpdate() || RECEIVED ZERO LENGTH MESSAGE\n");
		return ERROR;
	}


	for(i = 0; i < par.numberOfNew; i++)	{
		par.New[i] = *((NEW_SLOTS_TYPE* )&msg[ 2 + i*sizeof(NEW_SLOTS_TYPE) ]);
		//memcpy( &(par.New[i]), (NEW_SLOTS_TYPE* )&msg[ 2 + i*sizeof(NEW_SLOTS_TYPE)], sizeof(NEW_SLOTS_TYPE) );
	}
	for(j = 0; j < par.numberOfFree; j++)	{
		par.Free[j] = *((FREE_SLOTS_TYPE* )&msg[ 2 + i*sizeof(NEW_SLOTS_TYPE) + j*sizeof(FREE_SLOTS_TYPE)]);
		//memcpy( &(par.Free[j]), (FREE_SLOTS_TYPE* )&msg[ 2 + i*sizeof(NEW_SLOTS_TYPE) + j*sizeof(FREE_SLOTS_TYPE)], sizeof(FREE_SLOTS_TYPE) );
	}

	/*Freeing alloc[i].used according to the m.par.free*/
	for(i = 0; i < par.numberOfFree; i++)
	{
		for( j = 0; j < vCL->numberOfAdos; j++) {
			if( (par.Free[i].DeviceChannel.nodeId) == (vCL->alloc[j].used.nodeId)
					&& (par.Free[i].DeviceChannel.ch) == (vCL->alloc[j].used.ch)) {
				vCL->alloc[j].used.nodeId = 0;
				vCL->alloc[j].used.ch = 0;
			    break;
			}
		}
		if( j == vCL->numberOfAdos ) {
            PERROR("gUpdate() || CANNOT FREE: no such alloc.used exists \n");
        }
	}


	/*Check whether m.par.new already exist as alloc[i].used *
    *If such par.new exists nullify it                       */
	for(i = 0; i < par.numberOfNew; i++)
	{
		for( j = 0; j < vCL->numberOfAdos; j++) {
			if( (par.New[i].DeviceChannel.nodeId) == (vCL->alloc[j].used.nodeId)
					&& (par.New[i].DeviceChannel.ch) == (vCL->alloc[j].used.ch))
            {
 				PERROR("gUpdate() || par.new[%d] already exists as alloc[%d]->used. DISCARDED!\n", i, j);
                par.New[i].requiredSlots = 0;
                par.New[i].DeviceChannel.nodeId = 0;
                par.New[i].DeviceChannel.ch = 0;
			}
		}

	}


	/*Adding alloc[i].used according to the m.par.new								*
	 * TODO: burasi biraz karisik olabilir hangi alloc[i] ye koyacagimiz onemli 	*
	 * su an tam olarak kendi istedigi kadar slotu olan ilk alloc[j]'a kayitlaniyor*/
	for(i = 0; i < par.numberOfNew; i++ )
	{
		requiredSlots = par.New[i].requiredSlots;
		if (requiredSlots != 0)
		{
		    for( j = 0; j < vCL->numberOfAdos; j++)
		    {
                //check which unused alloc has the required slots
			    if( requiredSlots ==  vCL->alloc[j].num && vCL->alloc[j].used.nodeId == 0 && vCL->alloc[j].used.ch == 0 )
			    {
				    vCL->alloc[j].used.nodeId = par.New[i].DeviceChannel.nodeId;
				    vCL->alloc[j].used.ch = par.New[i].DeviceChannel.ch;
				    break;
			    }
		    }
        }
		if(j == vCL->numberOfAdos ) {
			NOTIFY("gUpdate() || FAILED TO ADD THE REQUEST TO A SUITABLE ALLOC\n");
		}
	}

	return OK;
}
STATUS DART::gRealTime(SLOT_TYPE* RTCL)
{
	U8 i;
	U8 j;
	(*RTCL) = NON_REAL_TIME_SLOT;
	for( i = 0; i < vCL->numberOfAdos; i++ )
	{
		for( j =0; j < vCL->alloc[i].num; j++ ) {
			if( vCL->cnt == vCL->alloc[i].slots[j] )
				(*RTCL) = REAL_TIME_SLOT;
		}
	}
	return OK;
}
STATUS DART::gMySlot(myCL_TYPE* myCL)
{
	U8 i;
	U8 j;
	myCL->mySlot = FALSE;
	myCL->ch = 0;

	for( i = 0; i < vCL->numberOfAdos; i++ )
	{
		for( j =0; j < vCL->alloc[i].num; j++ ) {
			if( vCL->cnt == vCL->alloc[i].slots[j] )
				break;
		}
		if(j != vCL->alloc[i].num){
			break;
		}
	}

	if( vCL->alloc[i].used.nodeId == NODE_ID )
	{
		/*may be omitted*/
		if(vCL->alloc[i].used.ch > TOTAL_NUMBER_OF_CHANNELS )
		{
			PERROR("!!ERROR: used.ch > TOTAL_NUMBER_OF_CHANNELS \n");
			return ERROR;
		}

		myCL->mySlot = TRUE;
		myCL->ch = vCL->alloc[i].used.ch;
	}

	return OK;
}

void DART::updateCountForDART()
{
	if ( (vCL->cnt = ((vCL->cnt) + 1)) == vCL->cyc)
		vCL->cnt = 0;
}

U16 DART::prepareCLHeader(U8* msg, void* parPtr)
{
	/*copy message parameters into the buffer that will be sent to IL  */
	U32 i,j;
	U16 CLHeaderLength = 0;
	DART_MESSAGE_PARAMETER_TYPE* par = (DART_MESSAGE_PARAMETER_TYPE*)parPtr;
	msg[0] = par->numberOfNew;
	msg[1] = par->numberOfFree;

	for( i = 0; i < par->numberOfNew; i++) {
		*((NEW_SLOTS_TYPE* )&msg[ 2 + i*sizeof(NEW_SLOTS_TYPE) ]) = par->New[i];
		//memcpy( &msg[ 2 + i*sizeof(NEW_SLOTS_TYPE) ], &(parPtr->New[i]), sizeof(NEW_SLOTS_TYPE));
	}
	for( j = 0; j < par->numberOfFree; j++ ) {
		*((FREE_SLOTS_TYPE* )&msg[ 2 + i*sizeof(NEW_SLOTS_TYPE) + j*sizeof(FREE_SLOTS_TYPE) ]) = par->Free[j];
		//memcpy( &msg[ 2 + i*sizeof(NEW_SLOTS_TYPE) + j*sizeof(FREE_SLOTS_TYPE) ], &(parPtr->Free[j]), sizeof(FREE_SLOTS_TYPE));
	}

	CLHeaderLength = 2 + i*sizeof(NEW_SLOTS_TYPE) + j*sizeof(FREE_SLOTS_TYPE); //+2 byte payloadLength

	return CLHeaderLength;
}
U8 DART::getCLHeaderLength(U8* msg)
{
	return 1 + 1 + (*&msg[0])*sizeof(NEW_SLOTS_TYPE) + (*&msg[1])*sizeof(FREE_SLOTS_TYPE);  //exclude 2 byte payloadLength
}

DART::~DART() {
	delete vCL;
}
